
#include <memory.h>
#include <stdio.h>

#define LAND_GRAPHICS_CORE

#include "init.h"

static const char* MISS_ERR = "miss vertex or fragment shader source";
static struct {
	LandGraphics* config;
	LandShaderBackend* backend;
}ctx = { 0 };

int
landInitShaderContext(LandGraphics* config, LandShaderBackend* backend) {
	ctx.config = config;
	ctx.backend = backend;
	return 0;
}

static void
freeShader(LandRef* ref) {
	LandShader* shader = (LandShader*)ref;
	ctx.backend->freeShader(shader);
	for (unsigned i = 0; i < shader->vsCount; i++) {
		free(shader->vs[i].data);
	}
	for (unsigned i = 0; i < shader->fsCount; i++) {
		free(shader->fs[i].data);
	}
	free(shader);
}

LAND_GRAPHICS_API LandShader*
landNewShader() {
	size_t size = ctx.backend->sizeofShader();
	LandShader* shader = landNewRef(size, freeShader);
	shader->vsCount = 0;
	shader->fsCount = 0;
	ctx.backend->newShader(shader);
	return shader;
}

LAND_GRAPHICS_API int
landShaderSource(LandShader* shader,
	LandShaderType type, const char* data, size_t size) {
	LandShaderSource* ss;
	unsigned* count;
	if (type == LAND_SHADER_VERTEX) {
		ss = shader->vs;
		count = &shader->vsCount;
	}
	else if (type == LAND_SHADER_FRAGMENT) {
		ss = shader->fs;
		count = &shader->fsCount;
	}
	else {
		return 1;
	}

	ss[*count].size = size;
	ss[*count].data = malloc(size);
	memcpy(ss[*count].data, data, size);
	(*count)++;
	return 0;
}

LAND_GRAPHICS_API int
landCompileShader(LandShader* shader, const char** err) {
	if(!shader->vsCount ||!shader->fsCount){
		*err = MISS_ERR;
		return 1;
	}
	int ret = ctx.backend->compileShader(shader, err);
	for (unsigned i = 0; i < shader->vsCount; i++) {
		free(shader->vs[i].data);
	}
	for (unsigned i = 0; i < shader->fsCount; i++) {
		free(shader->fs[i].data);
	}
	shader->vsCount = shader->fsCount = 0;
	return ret;
}
